home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Celestin Apprentice 5
/
Apprentice-Release5.iso
/
Source Code
/
Libraries
/
VideoToolbox 96.06.15
/
VideoToolboxSources
/
DrawGrating.c
< prev
next >
Wrap
Text File
|
1995-10-09
|
5KB
|
172 lines
/*
DrawGrating.c
Quickly draws a grating (cos, sin, square, or missing fundamental) with a
gaussian envelope in the current port, bounded by the supplied rect. The routine
is accurate and takes advantage of even and odd symmetries for speed. It is not
entirely general, e.g. orientation is restricted to vertical and horizontal.
Squarewaves have an undefined value at zero crossings, e.g. at the origin, so I've
shifted all the functions by a half pixel up and to the left.
WARNING: To compile this routine you'll need the header files nr.h and nrutil.h,
which are part of the Numerical Recipes in C, sold by Cambridge University Press
for about $100. (See Advice document.) Furthermore, within nr.h, you should make
sure that ANSI prototypes are enabled, since they provide the strictest and
safest prototype information. Similarly, set your compiler to REQUIRE prototypes.
The FLOAT type is my modification of the Numerical Recipes files, as explained in
the "Numerical Recipes.doc" file in Notes. (Bosco Tjan reports that you need the
current version, 2, since version 1 omits the lvector() function.)
HISTORY:
11/2/94 dgp shrink by s->noiseCheckSize, since it will later be expanded by that amount.
3/26/95 dgp as requested by Manoj, there are now separate space constants along and across
bars.
6/16/95 dgp replace "noiseCheckSize" by "signalCheckSize".
6/17/95 dgp changed "signalBounds" in first line to "stimulusBounds"
6/17/95 dgp eliminated all reference to s->signalContrast, since that applies to the
entire sequence of images.
*/
//#include "TextInNoise.h"
#include "nr.h" /* prototypes of Numerical Recipes and definition of FLOAT */
#include "nrutil.h"
enum{kCosinewave=0,kSinewave,kSquarewave,kMissingFundamental};// gratingType
typedef struct{
FLOAT degreesPerPixel;
FLOAT spatialFrequency,spaceConstantAlongBars,spaceConstantAcrossBars;
Rect bounds;
Point origin; // origin of the functions will be half a pixel up and to the left of this.
int gratingType;
int checkSize;
Boolean vertical;
int eAmplitude,eOffset;
}GratingSpec;
void DrawGrating(GratingSpec *g);
#undef MAX
#undef MIN
#define MAX(a,b) ((a) > (b) ? (a) : (b))
#define MIN(a,b) ((a) < (b) ? (a) : (b))
void DrawGrating(GratingSpec *g)
{
unsigned long *gratingPix;
FLOAT *fX,*fXEnvelope,*fY,*fTemp,w,e1,b,dc,a;
int iMax,width,fXSymmetry=0,fYSymmetry=0;
enum{kEven=1,kOdd};
Rect r;
int i,j;
int leftEdge,verticalOrigin;
r=g->bounds;
OffsetRect(&r,-g->origin.h,-g->origin.v);
ShrinkRect(&r,g->checkSize,g->checkSize); // Shrink
iMax=MAX(r.right,-r.left)-1;
iMax=MAX(iMax,MAX(r.bottom,-r.top)-1);
fX=vector(-iMax-1,iMax);
fXEnvelope=vector(-iMax-1,iMax);
fY=vector(-iMax-1,iMax);
width=r.right-r.left;
b=1/(g->spaceConstantAlongBars/g->degreesPerPixel);
b*=g->checkSize; // Shrink
fYSymmetry=kEven;
for(i=0;i<=iMax;i++){
a=(i+0.5)*b;
fY[-i-1]=fY[i]=exp(-a*a);
}
if(g->spaceConstantAlongBars!=g->spaceConstantAcrossBars){
b=1/(g->spaceConstantAcrossBars/g->degreesPerPixel);
b*=g->checkSize; // Shrink
for(i=0;i<=iMax;i++){
a=(i+0.5)*b;
fXEnvelope[-i-1]=fXEnvelope[i]=exp(-a*a);
}
}else{
for(i=0;i<=iMax;i++) fXEnvelope[-i-1]=fXEnvelope[i]=fY[i];
}
assert(fYSymmetry==kEven);
w=2*PI*g->spatialFrequency*g->degreesPerPixel;
w*=g->checkSize; // Shrink
e1=g->eAmplitude;
switch(g->gratingType){
case kCosinewave:
fXSymmetry=kEven;
for(i=0;i<=iMax;i++){
fX[-i-1]=fX[i]=e1*fXEnvelope[i]*cos((i+0.5)*w);
}
break;
case kSinewave:
fXSymmetry=kOdd;
for(i=0;i<=iMax;i++){
fX[i]=e1*fXEnvelope[i]*sin((i+0.5)*w);
fX[-i-1]=-fX[i];
}
break;
case kSquarewave:
fXSymmetry=kOdd;
for(i=0;i<=iMax;i++){
if(sin((i+0.5)*w)>=0)fX[i]=1;
else fX[i]=-1;
fX[i]*=e1*fXEnvelope[i];
fX[-i-1]=-fX[i];
}
break;
case kMissingFundamental:
fXSymmetry=kOdd;
for(i=0;i<=iMax;i++){
a=sin((i+0.5)*w);
fX[i]=(a>0)?1:-1;
fX[i]-=(4/PI)*a;
fX[i]*=e1*fXEnvelope[i];
fX[-i-1]=-fX[i];
}
break;
}
if(!g->vertical){
fTemp=fX;
i=fXSymmetry;
fX=fY;
fXSymmetry=fYSymmetry;
fY=fTemp;
fYSymmetry=i;
}
gratingPix=lvector(-iMax-1,iMax);
dc=g->eOffset+0.5;
leftEdge=r.left+g->origin.h/g->checkSize;
verticalOrigin=g->origin.v/g->checkSize;
for(j=iMax;j>=0;j--){
if(j>=r.bottom && -j-1<r.top)continue;
switch(fXSymmetry){
case kEven:
for(i=iMax;i>=0;i--)gratingPix[-i-1]=gratingPix[i]=dc+fY[j]*fX[i];
break;
case kOdd:
for(i=iMax;i>=0;i--){
a=fY[j]*fX[i];
gratingPix[i]=dc+a;
gratingPix[-i-1]=dc-a;
}
break;
default:
assert(0);
}
if(j<r.bottom)SetPixelsQuickly(leftEdge,j+verticalOrigin,&gratingPix[r.left],width);
if(-j-1>=r.top){
switch(fYSymmetry){
case kEven:
break;
case kOdd:
for(i=iMax;i>=-iMax-1;i--)gratingPix[i]=dc-(gratingPix[i]-dc);
break;
default:
assert(0);
}
SetPixelsQuickly(leftEdge,-j-1+verticalOrigin,&gratingPix[r.left],width);
}
}
free_lvector(gratingPix,-iMax-1,iMax);
free_vector(fX,-iMax-1,iMax);
free_vector(fXEnvelope,-iMax-1,iMax);
free_vector(fY,-iMax-1,iMax);
}